package loja;

import helpers.Banco;
import helpers.Categoria;
import helpers.Valor;
import interfaces.ProdutoInterface;

import java.awt.Image;
import java.awt.Toolkit;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Comparator;
import java.sql.Date;
import java.util.TreeSet;

import exceptions.ProdutoJaExistenteException;

public class Produto implements ProdutoInterface, Comparable<Produto> {

	private int id;

	private int quantidadeCarrinho;

	private int quantidadeEstoque;

	private String descricao;

	private String nome;

	private Valor valor;

	private String fabricante;

	private Image imagem;

	private Date dataDeFabricacao;

	private Categoria categoria;

	private Produto(int quantidadeEstoque, double valorCompra, String nome,
			String fabricante, Date dataDeFabricacao, Categoria categoria) {
		this.quantidadeEstoque = quantidadeEstoque;
		this.quantidadeCarrinho = quantidadeEstoque;
		this.nome = nome;
		valor = new Valor(0, valorCompra);
		this.fabricante = fabricante;
		this.dataDeFabricacao = dataDeFabricacao;
		this.categoria = categoria;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public Image getImagem() {
		return imagem;
	}

	public void setImagem(Image imagem) {
		this.imagem = imagem;
	}

	public int getQuantidadeEstoque() {
		return quantidadeEstoque;
	}

	public int getQuantidadeCarrinho() {
		return quantidadeCarrinho;
	}

	public double getValorVenda() {
		return valor.getValorVenda();
	}

	public double getValorCompra() {
		return valor.getValorCompra();
	}

	protected void setValorVenda(double valorVenda) {
		valor.setValorVenda(valorVenda);
	}

	public Date getDataDeFabricacao() {
		return dataDeFabricacao;
	}

	public String getFabricante() {
		return fabricante;
	}

	public Categoria getCategori() {
		return categoria;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getNome() {
		return nome;
	}

	public void setQuantidadeCarrinho(int quantidadeCarrinho) {
		this.quantidadeCarrinho = quantidadeCarrinho;
	}

	@Override
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME
				* result
				+ ((dataDeFabricacao == null) ? 0 : dataDeFabricacao.hashCode());
		result = PRIME * result
				+ ((descricao == null) ? 0 : descricao.hashCode());
		result = PRIME * result
				+ ((fabricante == null) ? 0 : fabricante.hashCode());
		result = PRIME * result + id;
		result = PRIME * result + ((nome == null) ? 0 : nome.hashCode());
		result = PRIME * result + quantidadeCarrinho;
		result = PRIME * result + quantidadeEstoque;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Produto other = (Produto) obj;
		if (dataDeFabricacao == null) {
			if (other.dataDeFabricacao != null)
				return false;
		} else if (!dataDeFabricacao.equals(other.dataDeFabricacao))
			return false;
		if (descricao == null) {
			if (other.descricao != null)
				return false;
		} else if (!descricao.equals(other.descricao))
			return false;
		if (fabricante == null) {
			if (other.fabricante != null)
				return false;
		} else if (!fabricante.equals(other.fabricante))
			return false;
		if (id != other.id)
			return false;
		if (nome == null) {
			if (other.nome != null)
				return false;
		} else if (!nome.equals(other.nome))
			return false;
		if (quantidadeCarrinho != other.quantidadeCarrinho)
			return false;
		if (quantidadeEstoque != other.quantidadeEstoque)
			return false;
		return true;
	}

	public String toString() {
		return this.getNome();
	}

	public void retiraQuantidadeEstoque(int i) {
		quantidadeEstoque -= i;
		String sql="UPDATE Produto SET qtd_estoque=" + quantidadeEstoque + "WHERE id_produto=" + this.id;
		Banco.executeQuery(sql);
	}

	public void adicionaQuantidadeEstoque(int i) {
		quantidadeEstoque += i;
		String sql="UPDATE Produto SET qtd_estoque=" + quantidadeEstoque + "WHERE id_produto=" + this.id;
		Banco.executeQuery(sql);
	}

	public void retiraQuantidadeCarrinho(int i) {
		quantidadeCarrinho -= i;
		String sql="UPDATE Produto SET qtd_carrinho=" + quantidadeCarrinho + "WHERE id_produto=" + this.id;
		Banco.executeQuery(sql);
	}

	public void adicionaQuantidadeCarrinho(int i) {
		quantidadeCarrinho += i;
		String sql="UPDATE Produto SET qtd_carrinho=" + quantidadeCarrinho + "WHERE id_produto=" + this.id;
		Banco.executeQuery(sql);
	}

	public static boolean adicionaProduto(int quantidadeEstoque,
			double valorCompra, double valorVenda, String nome,
			String fabricante, Date dataDeFabricacao, Categoria categoria)
			throws ProdutoJaExistenteException {

		String queryTot = "select count(id_produto) from produto where nome = '"
				+ nome + "'";
		int tot = Banco.getQuantidade(queryTot);

		if (tot >= 1)
			throw new ProdutoJaExistenteException();

		String sql = "insert into produto (qtd_estoque,nome,vl_compra,vl_venda,fabricante,dt_fabricacao,categoria) "
				+ "values (?,?,?,?,?,?,?)";
		try {
			PreparedStatement ps = Banco.prepareStatement(sql);
			ps.setInt(1, quantidadeEstoque);
			ps.setString(2, nome);
			ps.setDouble(3, valorCompra);
			ps.setDouble(4, valorVenda);
			ps.setString(5, fabricante);
			ps.setDate(6, dataDeFabricacao);
			ps.setInt(7, categoria.getId());
			return Banco.executePreparedStatement(ps);

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}

	public static int quantidadePorCategoria(Categoria c) {
		int idCategoria = c.getId();
		String sql = "Select * from produto where categoria = " + idCategoria;
		return Banco.getQuantidade(sql);
	}	
	public static Produto getProdutoById(int id){
		String sql="select * from Produto where id_Produto="+id;
		ResultSet rs=Banco.retrieveQuery(sql);
		
		try {
			rs.first();

			int qtd_carrinho=rs.getInt("qtd_carrinho");
			int id_cliente=rs.getInt("id_cliente");
			String nome = rs.getString("nome");
			int qtd_estoque=rs.getInt("qtd_estoque");
			double vl_venda=rs.getDouble("vl_venda");
			double vl_compra=rs.getDouble("vl_compra");
			String fabricante=rs.getString("fabricante");
			//Date data=rs.get
			//Image imagem=(Image)rs.getObject("imagem");
			Date data = null;
			Image imagem = null;
			int id_Produto=rs.getInt("id_produto");
			int categoria =rs.getInt("categoria");
			Categoria categoriaEnum=Categoria.getCategoriaById(categoria);
			
			
			Produto p = new Produto(qtd_estoque,vl_compra,nome,fabricante,data,categoriaEnum);
			return p;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	
	private static TreeSet<Produto> getProdutoByResultSet(
			Comparator<Produto> comparador, ResultSet rs, int primeiro,
			int quantidade) {
		TreeSet<Produto> produtos = new TreeSet<Produto>(comparador);

		Image imagem = null;

		try {
			if (!rs.absolute(primeiro)) {
				return produtos;
			}

			int tot = 0;

			while (rs.next() & tot <= quantidade) {
				tot++;

				int id = rs.getInt("id_produto");
				int qtd_estoque = rs.getInt("qtd_estoque");
				int qtd_carrinho = rs.getInt("qtd_carrinho");
				String nome = rs.getString("nome");
				String descricao = rs.getString("descricao");
				Double valorVenda = rs.getDouble("vl_venda");
				Double valorCompra = rs.getDouble("vl_compra");
				String fabricante = rs.getString("fabricante");
				InputStream is = rs.getBinaryStream("imagem");

				if (is != null) {
					ByteArrayOutputStream output = new ByteArrayOutputStream();
					int al = is.read();
					while (al >= 0) {
						output.write((char) al);
						al = is.read();
					}
					imagem = Toolkit.getDefaultToolkit().createImage(
							output.toByteArray());
				}

				Date dataDeFabricao = rs.getDate("dt_fabricacao");
				Categoria categoria = Categoria.getCategoriaById(rs
						.getInt("categoria"));

				Produto p = new Produto(qtd_estoque, valorCompra, nome,
						fabricante, dataDeFabricao, categoria);
				p.setId(id);
				p.setQuantidadeCarrinho(qtd_carrinho);
				p.setValorVenda(valorVenda);
				p.setDescricao(descricao);
				p.setImagem(imagem);
				produtos.add(p);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			rs.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return produtos;
	}

	public static TreeSet<Produto> getProdutosByNome(Comparator<Produto> c,
			int primeiro, int quantidade, String busca) {

		String sql = "select * from produto where nome like '%" + busca + "%'";

		ResultSet rs = Banco.retrieveQuery(sql);

		return getProdutoByResultSet(c, rs, primeiro, quantidade);
	}

	public static TreeSet<Produto> getProdutosByCategoriaFabricante(
			Comparator<Produto> comparator, int primeiro, int quantidade,
			Categoria cat, String fabricante) {

		int catId = cat.getId();

		String sql = "select * from produto where categoria = " + catId
				+ "and fabricante = " + fabricante + " limit " + primeiro
				+ ", " + quantidade;

		ResultSet rs = Banco.retrieveQuery(sql);

		return getProdutoByResultSet(comparator, rs, primeiro, quantidade);
	}

	public int compareTo(Produto o) {
		return this.getNome().compareToIgnoreCase(o.getNome());
	}
}
